import os
import glob
import sys
import copy
from typing import Union, List
from ExcelAPI import *
from SVDClasses import *

"""
    svd_info["device"] = info_of_device
    svd_info["cpu"] = info_of_cpu
    svd_info["peripherals_dic"] = {}
    svd_info["peripherals_dic"]["overview"] = peripherals_overview_infos
    svd_info["peripherals_dic"]["alias"] = peripheral_alias
    svd_info["peripherals_dic"]["headerStructNameGroup"] = peripheral_headerStructNameGroup    
    svd_info["peripherals"] = {}
    svd_info["peripherals"][peripheralname] = info_of_one_peripheral{}
"""
    
def gen_svd_string_from_info(svd_info :dict):
    device = Device.gen_inst_from_dict(svd_info["device"])
    if not device :
        print(f"[Error]Fail to gen DEVICE inst!!! \n")
        return ""
    
    cpu = CPU.gen_inst_from_dict(svd_info["cpu"])
    if not cpu :
        print(f"[Error]Fail to gen CPU inst!!! \n")
        return ""
    
    device.SetCPU(cpu)    
        
    #遍历外设
    for peripheral,peripheral_dic in svd_info["peripherals"].items():
        
        #需要判断是不是需要derivedFromStr
        derivedFromStr = get_peripheral_derivedFromStr(svd_info["peripherals"][peripheral],svd_info["peripherals_dic"]["headerStructNameGroup"])
        svd_info["peripherals"][peripheral]["derivedFrom"] = derivedFromStr
        
        #生成这个peripheral的inst
        peripheral_inst = Peripheral.gen_inst_from_dict(peripheral_dic)        
        if not peripheral_inst :
            print(f"[Error]Fail to gen peripheral inst!!! \n")
            return ""
        
        # 如果这个peripheral有derivedFrom,那么这个peripheral的寄存器细节就不看了
        if derivedFromStr != "" :
            # 删除registers, 避免后面valid检查出现空值
            del peripheral_inst.registers
            pass
        else :
            
            attr_is_valid_registers = True
            #遍历peripheral的regs
            peripheral_obj = svd_info["peripherals"][peripheral]
            if 'registers' not in peripheral_obj:
                namestr = peripheral_dic["name"]
                print(f"[Notice] peripheral[{namestr}] has no 'register' attr \n")
                attr_is_valid_registers = False
            
            if attr_is_valid_registers :
                svd_registers = peripheral_obj["registers"]
                if not (svd_registers and len(svd_registers) > 0):
                    namestr = peripheral_dic["name"]
                    print(f"[Warning] peripheral[{namestr}] has no register\n")
                    attr_is_valid_registers = False
            
            if attr_is_valid_registers :
                for register, register_dic in svd_registers.items():

                    register_inst = Register.gen_inst_from_dict(register_dic)
                    if not register_inst :                
                        namestr = register_dic["name"]
                        print(f"[Error]Fail to gen register[{namestr}] inst!!! \n")
                        return ""
                    
                    #遍历register的fields
                    svd_fields = register_dic["fields"]
                    if not (svd_fields and len(svd_fields) > 0): 
                        namestr = register_dic["name"]
                        print(f"[Warning] {peripheral}[{namestr}] has no fields?\n")
                        
                    else :      
                        for field,field_dic in svd_fields.items():
                            init_para_check_res_str = Field.check_init_paremeters(field_dic)
                            if init_para_check_res_str != "" :
                                print(f"[Error][{peripheral}][{register}][{field}] init parameter check failed ! reason : {init_para_check_res_str}\n")
                                continue
                                
                            field_inst = Field.gen_inst_from_dict(field_dic)
                            if not field_inst :
                                namestr = field_dic["name"]
                                print(f"[Error]Fail to gen field[{namestr}] inst!!! \n")
                                return ""
                            
                            if field == 'CMD' :
                                pass
                            #获取enum信息,有很多enum的话要遍历
                            #try:
                            if "enumdict" in field_dic:
                                enumdict = field_dic["enumdict"]      
                                if False and (enumdict["name"] is None or enumdict["name"] == "") :
                                    #没有名字就继续
                                    pass
                                else :
                                    #创建枚举dict
                                    fieldEnum = EnumeratedValues(enumdict["name"])
                                    #获得enum的list,每个enumvalue都是一个dict
                                    enumList = field_dic["enumdict"]["values"]
                                    for enumValueDict in enumList:
                                        fieldEnumValue = EnumeratedValue.gen_inst_from_dict(enumValueDict)
                                        fieldEnum.AddEnumValue(fieldEnumValue)
                                    field_inst.SetEnumeratedValues(fieldEnum)
                                                    
                            #except Exception as e:
                            #     print(f"[Error]enumdict in feild [{field}] of register [{register}]!!! \n")
                            #    continue         
                            
                            register_inst.AddField(field_inst)
                    
                    peripheral_inst.AddRegister(register_inst)
            else : # else of attr_is_valid_registers
                # 如果外设外设就是没有registers这个元素，要把peripheral_inst的registers这个属性删除，以规避后面validcheck环节
                # 这个情况在写表格过程中信息没完善就执行脚本时会发生
                try:
                    del peripheral_inst.registers
                except:
                    print(f"[Notice] peripheral[{peripheral}] has no registers info, del 'registers' attr\n")
            
        device.AddPeripheral(peripheral_inst)
            
    
    errcnt = device.ValidCheck()
    if errcnt :
        print(f"[Error] errors are detect in device valid check, please fix the errors \n")
        return ""
    
    #return device.toString()
    return device.toXmlStr()

def save_to_file(file_path: str, strToSave: str):
    with open(file_path, mode='w', encoding='utf-8') as file:
        file.write(strToSave)
        print(f"{file_path} saved successfully.\n");
def TestStrings():    
    print("TestStrings:===============\n")
    Device.TestString()
    print("===========================\n\n")
def ValidCheck():    
    print("ValidCheck=================\n")
    dev = Device.GetTestObject()
    errcnt = dev.ValidCheck();
    print(f"{errcnt} errors found.\n")
    print("===========================\n\n")
def GetAttitudeCSV():
    dev = Device.GetTestObject()
    csvStr = dev.GetAttributeCSVString()
    csvStr += dev.cpu.GetAttributeCSVString()
    save_to_file("attitude.csv",csvStr)
def get_xlsx_files(path_or_file: Union[str, List[str]]) -> List[str]:
    # 如果参数是列表，逐个处理每个路径
    if isinstance(path_or_file, list):
        result_files = []
        for item in path_or_file:
            result_files.extend(get_xlsx_files(item))  # 递归调用
        return result_files
    
    # 如果参数是字符串，继续处理
    abs_path = os.path.abspath(path_or_file)

    # 判断是否是文件
    if os.path.isfile(abs_path):
        file_name = os.path.basename(abs_path)
        # 判断文件扩展名是否为 .xlsx
        if not file_name.startswith('~$') and file_name.endswith('.xlsx'):
            return [abs_path]  # 返回文件的绝对路径
        else:
            return []  # 不是xlsx文件，返回空列表

    # 判断是否是目录
    elif os.path.isdir(abs_path):
        # 使用 glob 模块查找所有的 .xlsx 文件
        xlsx_files = glob.glob(os.path.join(abs_path, '*.xlsx'))
        xlsx_files_output = []
        for abs_path in xlsx_files:
            file_name = os.path.basename(abs_path)
            if not file_name.startswith('~$') and file_name.endswith('.xlsx'):
                xlsx_files_output.append(abs_path)            
        return xlsx_files_output

    else:
        return []  # 既不是文件也不是目录，返回空列表
    
    
